package com.gis.controller;


import com.gis.dto.OilspillDTO;
import com.gis.dto.RedtideDTO;
import com.gis.dto.YearAndSeasonDTO;
import com.gis.entity.StationData;
import com.gis.exception.CustomException;
import com.gis.result.ResponseResult;
import com.gis.service.ModelPredictionService;
import com.gis.service.StationDataService;
import com.gis.service.WaterQualityDataService;
import com.gis.vo.PredictVO;
import com.gis.vo.WarningReportVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.util.List;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/predict")
@CrossOrigin(origins = "*")
@Tag(name = "预测预警")
public class ModelPredictionController {
    private final ModelPredictionService modelPredictionService;
    private final StationDataService stationDataService;
    private final WaterQualityDataService waterQualityDataService;


    @Operation(summary = "单参数预测")
    @Parameters({
            @Parameter(name = "type", description = "类型（水质、沉积物、生物质量）", required = true),
            @Parameter(name = "param", description = "参数", required = true),
            @Parameter(name = "model", description = "模型（线性回归，多层感知机，多项式回归，序列到序列，长短期网络）", required = false),
            @Parameter(name = "id", description = "站点id", required = true)
    })
    @GetMapping("/getParamPrediction")
    public ResponseResult<PredictVO> getParamPrediction(String type, String param, @RequestParam(required = false) String model, int id){
        PredictVO waterPredict = modelPredictionService.paramPredict(type, param, model, id);
        YearAndSeasonDTO latestYearAndSeason = waterQualityDataService.getLatestYearAndSeason(id);
        waterPredict.setYear(latestYearAndSeason.getNextYear());
        waterPredict.setSeason(latestYearAndSeason.getNextSeason());
        return ResponseResult.success(waterPredict);
    }

    // 这里正确的逻辑是 拿 与最新时间的  5个 连续数据 必须都存在 这个需求很变态
    // 简单点？ 就不管 就最新的5个数据 完了5个都没有就默认及格
    // 1 sql分别拿数据 预测整合到一个dto类里 评价
    @Operation(summary = "单站点预警预测")
    @Parameters({
            @Parameter(name = "type", description = "类型（赤潮、溢油）", required = true),
            @Parameter(name = "id", description = "站点id", required = true)
    })
    @GetMapping("/getWarningPredictionById")
    public ResponseResult<WarningReportVO> getWarningPredictionById(String type, int id){
        WarningReportVO reportVO = new WarningReportVO();
        StationData stationData = stationDataService.getById(id);
        BeanUtils.copyProperties(stationData,reportVO);
        YearAndSeasonDTO latestYearAndSeason = waterQualityDataService.getLatestYearAndSeason(id);
        reportVO.setYear(latestYearAndSeason.getNextYear());
        reportVO.setSeason(latestYearAndSeason.getNextSeason());
        if(type.equals("赤潮")){
            RedtideDTO redtideDTO = modelPredictionService.redtidePredict(id);
            reportVO.setLevel(redtideDTO.getResult().getName());
            return ResponseResult.success(reportVO);
        } else if (type.equals("溢油")) {
            OilspillDTO oilspillDTO = modelPredictionService.oilspillPredict(id);
            reportVO.setLevel(oilspillDTO.getResult().getName());
            return ResponseResult.success(reportVO);
        }else {
            throw new CustomException("无效类型");
        }
    }

    /**
     * 获取所有站点的预警数据
     * @param type
     * @return
     */
    @Operation(summary = "所有站点预警预测")
    @Parameters({
            @Parameter(name = "type", description = "类型（赤潮、溢油）", required = true),
    })
    @GetMapping("/getWarningPrediction")
    public ResponseResult<List<WarningReportVO>> getWarningPrediction(String type){
        if(type.equals("赤潮")){
            List<WarningReportVO> reportVOS = modelPredictionService.redtidePredictReport();
            return ResponseResult.success(reportVOS);
        } else if (type.equals("溢油")) {
            List<WarningReportVO> reportVOS = modelPredictionService.oilspillPredictReport();
            return ResponseResult.success(reportVOS);
        }else {
            throw new CustomException("无效类型");
        }
    }


    /**
     * 返回报告PDF
     * @param response
     */
    @Operation(summary = "所有站点预警预测报告")
    @Parameters({
            @Parameter(name = "type", description = "类型（赤潮、溢油）", required = true),
            @Parameter(name = "screenshot", description = "图片")
    })
    @PostMapping("/getReport")
    public void getReport(@RequestParam String type,
                          @RequestParam(required = false) String screenshot,
                          HttpServletResponse response) {
        // 封装返回的文件
        try {
            // 1. 调用 service 生成 PDF 并获取输出流
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            if (type.equals("赤潮")) {
                modelPredictionService.generateRedtidePredictReport(baos, screenshot);
            } else if (type.equals("溢油")) {
                modelPredictionService.generateOilspillPredictReport(baos, screenshot);
            } else {
                throw new CustomException("无效类型");
            }
            // 1. 设置响应头
            response.setContentType("application/pdf");
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");

            // 2. 设置文件名
            String filename = String.format("%s预警预测报告.pdf", type);
            String encodedFilename = URLEncoder.encode(filename, "UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFilename);

            // 3. 写入输出流
            response.setContentLength(baos.size());
            baos.writeTo(response.getOutputStream());
            response.flushBuffer();

        } catch (Exception e) {
            log.error("PDF生成失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            throw new CustomException("PDF生成失败");
        }
    }
}
